class Seiso::ImportMaster

  # Resolves item keys to their URIs.
  #
  # TODO Rename to UriResolver.
  #
  # Author:: Willie Wheeler
  # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
  # License:: Apache 2.0
  #
  class Util::ItemResolver

    def initialize(api)
      @log = Util::Logger.new "ItemResolver"
      @api = api

      # Note that this initialization doesn't generate any HTTP requests.
      @special_searches = {
        # http://ruby-journal.com/becareful-with-space-in-lambda-hash-rocket-syntax-between-ruby-1-dot-9-and-2-dot-0/
        'loadBalancers' => ->(k) { @api.loadBalancers.search.findByName(name: k) },
        'machines' => ->(k) { @api.machines.search.findByName(name: k) },
        'persons' => ->(k) { @api.persons.search.findByUsername(username: k) }
      }

      @uri_cache = {}
    end

    # Returns the item URI, or nil if either key is nil or the item doesn't exist.
    def item_uri(type, key)
      return nil if key.nil?

      @log.info "Getting item URI: type=#{type}, key=#{key}"
      item_uri = get_cached_uri(type, key)
      return item_uri unless item_uri.nil?

      search = @special_searches[type]

      if search == nil
        item = @api.send(type).search.findByKey(key: key)
      else # special search
        item = search.call key
      end

      begin
        # This returns the item's canonical URI, which is what we want.
        item_uri = item.links.self.href
        put_cached_uri(type, key, item_uri)
        item_uri
      rescue HyperResource::ClientError => e
        status = e.response.status
        body = e.response.body
        raise "Response error: status=#{status}, body=#{body}" unless status == 404
        @log.warn "#{type}/#{key} not found. Returning nil."
        return nil
      end
    end

    # TODO Implementation based on HTTP 1.1 keepalive. The resolution above is too slow.
    def item_uri_via_keepalive(type, key)
      @log.info "Getting item URL: type=#{type}, key=#{key}"
      # TODO
    end

    def get_cached_uri(type, key)
      type_cache = @uri_cache[type]
      return nil if type_cache.nil?
      type_cache[key]
    end

    def put_cached_uri(type, key, uri)
      if @uri_cache[type].nil?
        @uri_cache[type] = {}
      end
      @uri_cache[type][key] = uri
    end
  end
end
